package utils;

import static game.Settings.getChambersNumber;
import static game.Settings.getFactoriesNumber;
import static game.Settings.getJewelsNumber;
import static game.Settings.getStabelsNumber;
import static game.Settings.getWallsNumber;
import static game.Types.CHAMBER;
import static game.Types.FURNITURE;
import static game.Types.GOLD;
import static game.Types.GRANITE;
import static game.Types.GRANITE_FACTORY;
import static game.Types.JEWELERY;
import static game.Types.MONEY;
import static game.Types.MONEY_FACTORY;
import static game.Types.PLANK;
import static game.Types.PLANK_FACTORY;
import static game.Types.PRECIOUS_STONE;
import static game.Types.ROCK;
import static game.Types.STABLE;
import static game.Types.WALL;
import static game.Types.WOOD;

import java.util.List;

import game.Building;
import game.Chamber;
import game.Factory;
import game.Mine;
import game.PointOnMap;
import game.Resource;
import game.Types;
import game.Warehouse;

public class StrategyGameUtils {

	public static final String ANSI_RESET = "\u001B[0m";;
	public static final String ANSI_RED = "\u001B[31m";
	public static final String ANSI_GREEN = "\u001B[32m";
	public static final String ANSI_YELLOW = "\u001B[33m";
	public static final String ANSI_BLUE = "\u001B[34m";

	public static Types getType(String type) {
		if (type.equals("chamber")) {
			return CHAMBER;
		}
		if (type.equals("stable")) {
			return STABLE;
		}
		if (type.equals("wall")) {
			return WALL;
		}
		if (type.equals("wood")) {
			return WOOD;
		}
		if (type.equals("rock")) {
			return ROCK;
		}
		if (type.equals("graniteFactory")) {
			return GRANITE_FACTORY;
		}
		if (type.equals("moneyFactory")) {
			return MONEY_FACTORY;
		}
		if (type.equals("plankFactory")) {
			return PLANK_FACTORY;
		}
		if (type.equals("granite")) {
			return GRANITE;
		}
		if (type.equals("plank")) {
			return PLANK;
		}
		if (type.equals("money")) {
			return MONEY;
		}
		if (type.equals("preciousStone")) {
			return PRECIOUS_STONE;
		}
		if (type.equals("furniture")) {
			return FURNITURE;
		}
		if (type.equals("jewelry")) {
			return JEWELERY;
		}
		if (type.equals("gold")) {
			return GOLD;
		}
		return null;
	}
	
	public static Types getBasicType(Types type)
	{
		if (type == Types.MONEY)
			return Types.GOLD;
		if (type == Types.PLANK)
			return Types.WOOD;
		if (type == Types.GRANITE)
			return Types.ROCK;
		return null;
	}

	public static Types getBasicType(Types type) {
		if (type == MONEY)
			return GOLD;
		if (type == PLANK)
			return WOOD;
		if (type == GRANITE)
			return ROCK;
		return null;
	}

	public static Types getResourceTypeForMine(Types mineType) {
		switch (mineType) {
		case GOLD_MINE:
			return GOLD;
		case PRECIOUS_STONES_MINE:
			return PRECIOUS_STONE;
		}
		return null;
	}

	public static Types getResourceInputTypeForFactory(Types factoryType) {
		switch (factoryType) {
		case PLANK_FACTORY:
			return WOOD;
		case GRANITE_FACTORY:
			return ROCK;
		case MONEY_FACTORY:
			return GOLD;
		}
		return null;
	}

	public static Types getResourceOutputTypeForFactory(Types factoryType) {
		switch (factoryType) {
		case PLANK_FACTORY:
			return PLANK;
		case GRANITE_FACTORY:
			return GRANITE;
		case MONEY_FACTORY:
			return MONEY;
		}
		return null;
	}

	public static boolean isFactory(Types type) {
		return (type == PLANK_FACTORY || type == GRANITE_FACTORY || type == MONEY_FACTORY);
	}

	public static char getSymbol(Types type) {
		switch (type) {
		case MONEY_FACTORY:
			return 'm';
		case GRANITE_FACTORY:
			return 'g';
		case PLANK_FACTORY:
			return 'p';
		case WALL:
			return 'W';
		case STABLE:
			return 's';
		case JEWELERY:
			return 'j';
		case CHAMBER:
			return 'c';
		case WOOD:
			return 'w';
		case ROCK:
			return 'r';
		case GOLD:
			return 'G';
		case PRECIOUS_STONE:
			return 'M';
		}
		return '#'; // an unused symbol
	}

	public static int getOwner(int x, int y, int linesNumber, int columnsNumber) {
		if (x < linesNumber / 2 && y < columnsNumber / 2) {
			return 1;
		}
		if (x < linesNumber / 2 && y >= columnsNumber / 2) {
			return 2;
		}
		if (x >= linesNumber / 2 && y >= columnsNumber / 2) {
			return 3;
		}
		return 4;
	}

	public static void printMap(List<PointOnMap> map, int columnsNumber) {
		int index = 0;
		for (PointOnMap aPoint : map) {
			System.out.print(getColor(aPoint));
			System.out.print(aPoint.getSymbol());
			index++;
			if (index == columnsNumber) {
				index = 0;
				System.out.println();
			}
		}
	}

	private static String getColor(PointOnMap point) {
		int owner = point.getOwner();
		switch (owner) {
		case 1:
			return ANSI_RED;
		case 2:
			return ANSI_GREEN;
		case 3:
			return ANSI_YELLOW;
		case 4:
			return ANSI_BLUE;
		}
		return ANSI_RESET;
	}

	public static PointOnMap getPoint(List<PointOnMap> map, int x, int y) {
		for (PointOnMap point : map) {
			if (point.getX() == x && point.getY() == y) {
				return point;
			}
		}
		return null;
	}
	
	public static PointOnMap getPointWithSymbol (List<PointOnMap> map, char symbol)
	{
		for (PointOnMap point : map)
		{
			if (point.getSymbol() == symbol)
				return point;
		}
		return null;
	}

	public static PointOnMap getPointWithSymbol(List<PointOnMap> map,
			char symbol) {
		for (PointOnMap point : map) {
			if (point.getSymbol() == symbol)
				return point;
		}
		return null;
	}

	public static PointOnMap getFreePointWithSymbol(List<PointOnMap> map,
			int predefinedOwner, char symbol) {
		for (PointOnMap point : map) {
			if (point.getSymbol() == symbol && point.getOwner() == 0
					&& point.getPredefinedOwner() == predefinedOwner) {
				return point;
			}
		}
		return null;
	}

	public static Mine getMine(List<Mine> allMines, int x, int y) {
		for (Mine aMine : allMines) {
			if (aMine.getX() == x && aMine.getY() == y) {
				return aMine;
			}
		}
		return null;
	}
	
	public static Types getFactory(List<Building> buildings, Types resource)
	{
		for (Building aBuilding : buildings)
		{
			if ((resource == Types.ROCK) && (aBuilding.getType() == Types.GRANITE_FACTORY))
				return Types.GRANITE_FACTORY;
			if ((resource == Types.GOLD) && (aBuilding.getType() == Types.MONEY_FACTORY))
				return Types.MONEY_FACTORY;
			if ((resource == Types.WOOD) && (aBuilding.getType() == Types.PLANK_FACTORY))
				return Types.PLANK_FACTORY;
		}
		return null;
	}

	public static Types getFactory(Types resource) {
		switch (resource)
		{
		case ROCK:
			return GRANITE_FACTORY;
		case GOLD:
			return MONEY_FACTORY;
		case WOOD:
			return PLANK_FACTORY;
		}
		return null;
	}

	public static Warehouse getInputWarehouse(List<Warehouse> warehouses,
			Types type) {
		for (Warehouse aWarehouse : warehouses) {
			if (aWarehouse.getType().equals(
					getResourceInputTypeForFactory(type))) {
				return aWarehouse;
			}
		}
		return null;
	}

	public static Warehouse getOutputWarehouse(List<Warehouse> warehouses,
			Types type) {
		for (Warehouse aWarehouse : warehouses) {
			if (aWarehouse.getType().equals(
					getResourceOutputTypeForFactory(type))) {
				return aWarehouse;
			}
		}
		return null;
	}

	public static void stopAllFactories(List<Building> buildings) {
		for (Building aBuilding : buildings) {
			if (aBuilding instanceof Factory) {
				((Factory) aBuilding).cancel();
			}
		}

	}

	public static boolean hasBuiltAll(List<Building> buildings) {
		int expectedNumber = (getChambersNumber() + getJewelsNumber()
				+ getStabelsNumber() + getWallsNumber() + getFactoriesNumber());
		if (buildings.size() == expectedNumber)
			return true;
		return false;
	}

	public static Resource getResourceWithType(List<Resource> resources,
			Types type) {
		for (Resource aResource : resources) {
			if (aResource.getType().equals(type)) {
				return aResource;
			}
		}
		return null;
	}

	public static Chamber getUnfurnishedChamber(List<Building> buildings) {
		for (Building b : buildings) {
			if (b instanceof Chamber)
				if (!((Chamber) b).isFurnished())
					return (Chamber) b;
		}
		return null;
	}
}
